use sha2::{Digest, Sha256};
use serde::{Serialize, Deserialize};
use chrono::Utc;
use super::transaction::Transaction;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Block {
    pub index: u64,
    pub timestamp: i64,
    pub transactions: Vec<Transaction>,
    pub previous_hash: String,
    pub nonce: u64,
    pub hash: String,
}

impl Block {
    pub fn new(index: u64, transactions: Vec<Transaction>, previous_hash: String) -> Self {
        let timestamp = Utc::now().timestamp();
        let mut block = Block {
            index,
            timestamp,
            transactions,
            previous_hash,
            nonce: 0,
            hash: String::new(),
        };
        block.hash = block.calculate_hash();
        println!("正在生成区块 {} 的哈希: {}", index, block.hash);  // 调试输出
        block
    }

    fn calculate_hash(&self) -> String {
        let input = format!(
            "{}{}{:?}{}{}",
            self.index, self.timestamp, self.transactions, self.previous_hash, self.nonce
        );
        let mut hasher = Sha256::new();
        hasher.update(input.as_bytes());
        hex::encode(hasher.finalize())
    }
}

#[derive(Debug)]
pub struct Blockchain {
    pub chain: Vec<Block>,
    pub difficulty: usize,
}

impl Blockchain {
    pub fn new() -> Self {
        // 修正创世区块初始化逻辑
        let mut genesis = Block::new(0, vec![], "0".to_string());
        genesis.hash = genesis.calculate_hash();  // 确保哈希被正确计算
        
        Blockchain {
            chain: vec![genesis],  // 现在链的第一个区块有有效哈希
            difficulty: 4,
        }
    }

    pub fn add_block(&mut self, transactions: Vec<Transaction>) {
        let last_block = self.chain.last().unwrap();
        let mut new_block = Block::new(
            last_block.index + 1,
            transactions,
            last_block.hash.clone()
        );
        new_block.hash = self.proof_of_work(&new_block);
        self.chain.push(new_block);
    }

    fn proof_of_work(&self, block: &Block) -> String {
        let target = "0".repeat(self.difficulty);
        let mut nonce = 0;
        loop {
            let hash = self.calculate_hash_with_nonce(block, nonce);
            if hash.starts_with(&target) {
                return hash;
            }
            nonce += 1;
        }
    }

    fn calculate_hash_with_nonce(&self, block: &Block, nonce: u64) -> String {
        let input = format!(
            "{}{}{:?}{}{}",
            block.index, block.timestamp, block.transactions, block.previous_hash, nonce
        );
        let mut hasher = Sha256::new();
        hasher.update(input.as_bytes());
        hex::encode(hasher.finalize())
    }
}

impl std::fmt::Display for Block {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "Block {{ index: {}, hash: {}..., prev_hash: {}... }}",
            self.index,
            &self.hash[..8],
            &self.previous_hash[..8]
        )
    }
}
